import dash
from dash import dcc
from dash import html
from dash.dependencies import Input, Output
import plotly.graph_objects as go
import pandas as pd

# 初始化 Dash 应用
app = dash.Dash(__name__)

# 初始化一个空的 DataFrame 来存储点的坐标
data = pd.DataFrame(columns=['x', 'y', 'z'])

# 定义应用布局
app.layout = html.Div([
    html.H1("三维散点图交互"),
    # 输入 x、y、z 坐标的输入框
    dcc.Input(id='input-x', type='number', placeholder='输入 x 坐标'),
    dcc.Input(id='input-y', type='number', placeholder='输入 y 坐标'),
    dcc.Input(id='input-z', type='number', placeholder='输入 z 坐标'),
    # 添加点的按钮
    html.Button('添加', id='add-button'),
    # 删除点的按钮
    html.Button('删除', id='delete-button'),
    # 显示三维散点图的组件
    dcc.Graph(id='scatter-3d')
])

# 回调函数，处理添加和删除点的操作
@app.callback(
    Output('scatter-3d', 'figure'),
    [Input('add-button', 'n_clicks'),
     Input('delete-button', 'n_clicks')],
    [dash.dependencies.State('input-x', 'value'),
     dash.dependencies.State('input-y', 'value'),
     dash.dependencies.State('input-z', 'value')]
)
def update_scatter_plot(add_clicks, delete_clicks, x, y, z):
    global data
    ctx = dash.callback_context
    if not ctx.triggered:
        button_id = None
    else:
        button_id = ctx.triggered[0]['prop_id'].split('.')[0]

    # 如果点击了添加按钮
    if button_id == 'add-button' and x is not None and y is not None and z is not None:
        new_point = pd.DataFrame({'x': [x], 'y': [y], 'z': [z]})
        data = pd.concat([data, new_point], ignore_index=True)
    # 如果点击了删除按钮
    elif button_id == 'delete-button' and not data.empty:
        data = data.iloc[:-1]

    # 创建三维散点图
    fig = go.Figure(data=[go.Scatter3d(
        x=data['x'],
        y=data['y'],
        z=data['z'],
        mode='markers+lines',  # 显示点和连线
        marker=dict(
            size=10,
            color='blue'
        )
    )])

    # 设置图形布局
    fig.update_layout(scene=dict(
        xaxis_title='X',
        yaxis_title='Y',
        zaxis_title='Z'
    ))

    return fig

if __name__ == '__main__':
    app.run_server(debug=True)